package com.xiaozeng.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaozeng.clients.CategoryClient;
import com.xiaozeng.clients.SearchClient;
import com.xiaozeng.param.*;
import com.xiaozeng.pojo.Picture;
import com.xiaozeng.pojo.Product;
import com.xiaozeng.product.mapper.PictureMapper;
import com.xiaozeng.product.mapper.ProductMapper;
import com.xiaozeng.product.service.ProductService;
import com.xiaozeng.utils.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author: xiaozeng
 * @Date: 2022 11
 * @Description:
 **/
@Service
@Slf4j
public class ProductServiceImpl extends ServiceImpl<ProductMapper,Product> implements ProductService {
    //引入feign客户端，需要在启动类添加配置注解
    @Autowired
    private CategoryClient categoryClient;
    @Autowired
    private SearchClient searchClient;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private PictureMapper pictureMapper;

    /**
     * @Cacheable 调用方法，查询是否有缓存，有直接走缓存，没有走方法，将方法的返回值进行缓存
     * 位置：添加到方法和类上
     * 参数：
     *      value = String{} 配置缓存的 配置缓存‘分区’，相当于缓存的标示！
     *      key   = String   配置缓存的 ‘分区’下的具体表示，此处支持SpringEL表达式，动态命名
     *      cacheManager = String 选择配置类中的缓存配置对象beanname，不选走默认！
     *      condition = String 注解生效条件， 支持SpringEl表达式 例如： "#result != null"
     *                             结果不为null，进行缓存！
     */

    @Cacheable(value = "list.product",key = "#categoryName")
    @Override
    public Result promo(String categoryName) {
        Result result = categoryClient.queryByName(categoryName);

        if (result.getCode().equals(Result.FAIL)) {
            log.info("ProductServiceImpl.promo业务结束，结果:{}","类别查询失败!");
            return result;
        }
        //根据类别名称 调用 feign客户端访问类别服务获取类别的数据
        /*Category category =(Category) result.getData();
        Integer categoryId = category.getCategoryId();*/
        // 类别服务中 data = category
        // 但是经过feign 会将数据类型转为json
        // product服务 接收到的是 LinkedHashMap格式

        LinkedHashMap<String,Object>  map = (LinkedHashMap<String, Object>) result.getData();
        Integer categoryId = (Integer) map.get("categoryId");
        //封装查询参数，继续根据类别id查询商品数据  [热门 销售量倒序 查询7]
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("category_id",categoryId);
        queryWrapper.orderByDesc("product_sales");

        IPage<Product> page = new Page<>(1,7);

        //返回的是包装数据! 内部有对应的商品集合,也有分页的参数 例如: 总条数 总页数等等
        page = productMapper.selectPage(page, queryWrapper);

        List<Product> productList = page.getRecords(); //指定页的数据
        long total = page.getTotal(); //获取总条数

        log.info("ProductServiceImpl.promo业务结束，结果:{}",productList);

        return Result.ok("数据查询成功",productList,total);
    }
    @Cacheable(value = "list.product",key = "#productHotParam.categoryName")
    @Override
    public Result hots(ProductHotParam productHotParam) {
        Result result = categoryClient.hots(productHotParam);

        if(result.getCode().equals(Result.FAIL)){
            log.info("ProductServiceImpl.hots业务结束，结果:{}",result.getMsg());
            return result;
        }

        List<Object> ids = (List<Object>) result.getData();

        //进行商品数据查询
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("category_id",ids);
        queryWrapper.orderByDesc("product_sales");

        IPage<Product> page = new Page<>(1,7);

        page = productMapper.selectPage(page,queryWrapper);

        List<Product> records = page.getRecords();

        log.info("ProductServiceImpl.hots业务结束，结果:{}",records);

        return Result.ok("多类别热门商品查询成功!", records);
    }

    @Cacheable(value = "list.category",key = "#root.methodName")
    @Override
    public Result cList() {
        Result result = categoryClient.list();
        log.info("ProductServiceImpl.cList业务结束，结果:{}",result);
        return result;
    }
    @Cacheable(value = "list.product",key =
            "#productIntegerParam.categoryID+" +
                    "'-'+#productIntegerParam.currentPage+" +
                    "'-'+#productIntegerParam.pageSize")
    @Override
    public Object byCategory(ProductIntegerParam productIntegerParam) {

        //1.拆分请求参数
        List<Integer> categoryID = productIntegerParam.getCategoryID();
        int currentPage = productIntegerParam.getCurrentPage();
        int pageSize = productIntegerParam.getPageSize();

        //2.请求条件封装
        QueryWrapper<Product> productQueryWrapper = new QueryWrapper<>();
        if (categoryID != null && categoryID.size() > 0){
            productQueryWrapper.in("category_id",categoryID);
        }
        IPage<Product> page = new Page<>(currentPage,pageSize);

        //3.数据查询
        IPage<Product> iPage = productMapper.selectPage(page, productQueryWrapper);

        //4.结果封装
        List<Product> productList = iPage.getRecords();
        long total = iPage.getTotal();

        Result ok = Result.ok(null, productList, total);

        log.info("ProductServiceImpl.byCategory业务结束，结果:{}",ok);
        return ok;
    }

    @Override
    public Object all(ProductIntegerParam productIntegerParam) {
        return byCategory(productIntegerParam);
    }

    @Cacheable(value = "product",key = "#productID")
    @Override
    public Object detail(Integer productID) {
        Product product = productMapper.selectById(productID);
        if (product==null){
            return Result.fail("查询不到商品信息");
        }
        Result ok = Result.ok(product);
        log.info("ProductServiceImpl.detail业务结束，结果:{}",ok);
        return ok;
    }

    @Cacheable(value = "picture",key = "#productID")
    @Override
    public Object pictures(Integer productID) {
        //参数封装
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("product_id",productID);
        //数据库查询
        List<Picture> pictureList = pictureMapper.selectList(queryWrapper);
        //结果封装
        if (pictureList==null){
            return Result.fail("查询不到商品信息");
        }
        Result result = Result.ok(pictureList);
        log.info("ProductServiceImpl.pictures业务结束，结果:{}",result);
        return result;
    }

    @Override
    public List<Product> list() {
        return productMapper.selectList(null);
    }

    @Override
    public Object search(ProductSearchParam productSearchParam) {
        Result result = searchClient.search(productSearchParam);

        log.info("ProductServiceImpl.search业务结束，结果:{}",result);
        return pictureMapper;
    }

    @Cacheable(value = "list.product",key = "#productCollectParam.productIds")
    @Override
    public List<Product> ids(ProductCollectParam productCollectParam) {

        List<Integer> productIds = productCollectParam.getProductIds();

        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("product_id",productIds);

        return productMapper.selectList(queryWrapper);
    }

    @Transactional
    @Override
    public void batchNumber(List<ProductNumberParam> productNumberParams) {

        //将productNumberParams转成map
        //使用id作为key, item做值, 比较相邻的两次key,如果相同,去掉重读!
        Map<Integer, ProductNumberParam> productNumberParamMap = productNumberParams.stream()
                .collect(Collectors.toMap(ProductNumberParam::getProductId, v -> v));

        //封装商品集合
        Set<Integer> productIds = productNumberParamMap.keySet();

        //查询
        List<Product> productList = baseMapper.selectBatchIds(productIds);
        //修改

        for (Product product : productList) {
            //设置新库存
            product.setProductNum(product.getProductNum() -
                    productNumberParamMap.get(product.getProductId()).getProductNum());
            //设置销售量
            product.setProductSales(product.getProductSales() +
                    productNumberParamMap.get(product.getProductId()).getProductNum());
        }

        //批量数据更新
        this.updateBatchById(productList);
    }

}
